package com.handpay.framework.swiper;

import android.content.Context;
import android.util.Log;

import com.handpay.framework.swiper.ic.IShowSelectApplication;
import com.handpay.framework.utils.CommonUtils;
import com.handpay.zztong.hp.log.HPLog;
import com.itron.android.ftf.Util;
import com.itron.protol.android.BLECommandController;
import com.itron.protol.android.CommandReturn;
import com.itron.protol.android.CommunicationListener;
import com.itron.protol.android.Customer;
import com.itron.protol.android.TransactionDateTime;
import com.itron.protol.android.TransactionInfo;
import com.itron.protol.android.TransationCurrencyCode;
import com.itron.protol.android.TransationTime;
import com.itron.protol.android.TransationType;
import com.mset.cardswiper.Convert;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Locale;
import java.util.concurrent.TimeoutException;

public class ItronI21BSwiper extends AbstractBbposSwiper implements CommunicationListener{

	private static final String TAG = "ItronSwiper";
	private Context context;
	protected AsynSwiperLock mLock;
	protected IShowSelectApplication mSelectApplication;
	public boolean isSwiperOk = false;
	private String strCSN = "";
	private static String macStr = "";
	private boolean isStop = true;
	private String mData = "";
	private BLECommandController itcommm;
	private byte[] random=null;
	byte[] cash="23347".getBytes();
	private String paraAddress;
	
	
	public ItronI21BSwiper(Context context, String address,IShowSelectApplication selectApplication) {
		HPLog.e(TAG, ">>>>ItronSwiper<<<<");
		
		this.context = context;
		mSelectApplication = selectApplication;
		isSwiperOk = true;
		mLock = new AsynSwiperLock();
		paraAddress = address;
		initSDK();
	}
	
	
	public void initSDK()
	{
		HPLog.e(TAG, ">>>>ItronSwiper:initSdk<<<<");
		try {
			if (itcommm == null) {
				itcommm = BLECommandController.GetInstance(context, this);
				
				//艾创刷卡器的打印日志
				/*Logger logger=Logger.getInstance(ItronI21BSwiper.class);
				logger.setDebug(true);*/
				
				}
		} catch (Exception e) {
			HPLog.e(TAG, ">>>>ItronSwiper:initSdk :Exception<<<<"+e);
			e.printStackTrace();
		}
	}
	
	
	public boolean openDevice()
	{
		Log.e(TAG,"open address:" + paraAddress);
		int i = itcommm.openDevice(paraAddress);
		if(i==0){		
			HPLog.e(TAG, ">>>>openDevice<<<<设备连接成功");
			isSwiperOk=true;
		}else{
			HPLog.e(TAG, ">>>>openDevice<<<<设备连接失败");
			isSwiperOk=false;
		}
		return isSwiperOk;
	}
	
	

	
	
	
	@Override
	public String getCSN() {
		
		if(openDevice()){
		HPLog.e(TAG, ">>>>getCSN<<<<");
		Customer customer = Customer.HAN_YIN;
		CommandReturn cmret = itcommm.getKsnI21(customer);
		if(cmret.csn!=null){
		String ksn = new String(cmret.csn, 0, cmret.csn.length);
		HPLog.e(TAG, ">>>>getCSN strCSN:<<<<" + ksn);
		strCSN = ksn.substring(0, 20);
		HPLog.e(TAG, ">>>>getCSN strCSN:<<<<" + strCSN);
			} 
		}
		return strCSN == null ? null : strCSN.toUpperCase(Locale.US);
		
	}

	@Override
	public boolean stopOperation() {
		HPLog.e(TAG, ">>>>stopOperation<<<<");
		isStop = false;
		mData = null;
		mHTData.clear();
		mLock.unlock(AsynSwiperLock.IDLE);
		if (itcommm != null) {
			// 刷卡器发送指令,使刷卡器进入刷卡状态以后接受到该指令退出刷卡状态,进入IDLE状态
			itcommm.stopSearchDevices();
		}
		return true;
	}

	@Override
	public boolean closeDevice() {
		HPLog.e(TAG, ">>>>closeDevice<<<<");
		stopOperation();
		isSwiperOk = false;
		context = null;
		mSelectApplication = null;
		if (itcommm != null) {
			// 删除控制器CSwiperController,释放资源
			itcommm.closeDevice();
			itcommm = null;
		}
		return true;
	}

	@Override
	public SwipeResult swipeCard(String factor, int timeout) {
		HPLog.e(TAG, ">>>>swipeCard<<<<");
		HPLog.e(TAG, factor);
		HPLog.e(TAG, "dateTime: " + factor.substring(0, 8));
		HPLog.e(TAG, "time: " + factor.substring(8, 14));
		isStop = true;
		CommandReturn cmdret = new CommandReturn();
		TransactionInfo info = new TransactionInfo();
		// 设置交易日期 格式: YYMMDD
		TransactionDateTime dateTime = new TransactionDateTime();
		dateTime.setDateTime(factor.substring(0, 8));
		// 设置交易时间 hhssmm
		TransationTime time = new TransationTime();
		time.setTime(factor.substring(8, 14));
		// 设置货币代码
		TransationCurrencyCode currencyCode = new TransationCurrencyCode();
		currencyCode.setCode("0156");
		// 设置交易类型 00 消费
		TransationType type = new TransationType();
		type.setType("00");

		info.setDateTime(dateTime);
		info.setCurrencyCode(currencyCode);
		info.setTime(time);
		info.setType(type);

		// 字节1
		// bit0＝0/1 表示随机有爱刷产生/由双方产生。
		// Bit1＝0/1 表示终端需要不上送/上送mac。
		// Bit2＝0/1 表示终端上送的卡号不屏蔽/屏蔽
		// Bit3＝0/1 不上送/上送各磁道的原始长度

		// Bit4=0/1磁道数据加密/不加密
		// Bit5=0/1上送/不上送PAN码
		// Bit6=0/1 55域不加密/加密
		// Bit7 =0/1 不上送/上送各磁道密文的长度
		// 字节2
		// bit0= 0/1 表示这个数据域参与mac计算/只有数据域内的磁道数据和随机数参与
		// Bit1 = 0/1 使用全部ic卡/银联标准55域

		// bit7----bit0

		// 翰银设置 byte4 bit2 =1
		String byte0 = "10001000";
		String byte1 = "00111011";
		String byte2 = "00000000";
		int flag0 = Util.binaryStr2Byte(byte0);
		int flag1 = Util.binaryStr2Byte(byte1);
		int flag2 = Util.binaryStr2Byte(byte2);
		cmdret = itcommm.statEmvSwiperI21((byte)0,
                new byte[]{(byte)flag0,(byte) flag1, (byte) flag2, 0x02},
                "123".getBytes(), "100",
                null, 30, info,Customer.HAN_YIN);
		 if((cmdret!=null)&&((cmdret.Return_Result==0X00))){
			 String PlainAccountKey = new String(cmdret.Return_CardNo,0,cmdret.Return_CardNo.length);
			 mHTData.put("cardType",  String.valueOf(cmdret.CardType));
			 mHTData.put(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY,  PlainAccountKey);
			 mHTData.put(IBusinessSwiper.BANK_DYNAMIC_KEY,  Util.BinToHex(cmdret.Return_PSAMRandom,0,cmdret.Return_PSAMRandom.length));
			 mHTData.put(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE,Util.BinToHex(cmdret.cardexpiryDate,0,cmdret.cardexpiryDate.length) );
			 mHTData.put(IBusinessSwiper.BANK_TRACK2_KEY, 
					 BusinessSwiper.autoFillTrack2((String.valueOf(cmdret.orignalTrackLengths[1]) +  
							 Util.BinToHex(cmdret.Return_PSAMTrack,0, cmdret.trackLengths[1])
							 .toUpperCase(Locale.US))));
			if (cmdret.CardSerial != null && cmdret.emvDataInfo != null) {
					mHTData.put(IBusinessSwiper.BANK_ICNUMBER, "0" + Util.BinToHex(cmdret.CardSerial,0,+cmdret.CardSerial.length));
					mHTData.put(IBusinessSwiper.BANK_DCDATA, Util.BinToHex(cmdret.emvDataInfo,0, cmdret.emvDataInfo.length));
				}
			 

		 }
		 if (null != mHTData.get(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY)) {
				SwipeResult result = new SwipeResult(SwipeStatus.SWIPE_OK, mHTData.get(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY));
				result.mCardType = mHTData.get("cardType");
				return result;
			}
		try {
			mLock.lock(timeout, AsynSwiperLock.NEW_SWIPE_CARD);
		} catch (TimeoutException te) {
			HPLog.i(TAG, "", te);
			return new SwipeResult(SwipeStatus.SWIPE_TIMEOUT);
		}
		if (null != mHTData.get(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY)) {
			SwipeResult result = new SwipeResult(SwipeStatus.SWIPE_OK, mHTData.get(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY));
			result.mCardType = mHTData.get("cardType");
			return result;
		}
		if (!isStop) {
			HPLog.i(TAG, "--isStop--" + isStop);
			return new SwipeResult(SwipeStatus.SWIPE_CANCEL);
		}
		
		
		
		
		return new SwipeResult(SwipeStatus.SWIPE_ERROR);
	}

	@Override
	public String encData(String data, String index, String factor) {
		HPLog.e(TAG, "encData-data: " + data + " index: " + index);
		factor = factor.substring(0, factor.length() - 2);
		HPLog.e(TAG, factor);
		if (ISwiperListener.KeyDataIndex.equals(index)) {
			data = formatData(data, 0);
			// data = formatDataAdpu(data);
			HPLog.e(TAG, "encData-data: " + data);
			byte[] temp=new byte[Util.HexToBin(data).length/2];
			System.arraycopy(Util.hexStringToByteArray(data), 0, temp, 0, temp.length);
			byte[]  cmdret = itcommm.psamEnc(0, Util.HexToBin(factor), Util.HexToBin(data));
			if (cmdret != null) {
				mData = Util.BinToHex(cmdret,0,cmdret.length);
			}
			return mData;
		} else if (PIN_INDEX.equals(index)) {
			byte[] tmpRandom = Util.HexToBin((Util.getCurrentDate()+Util.getCurrentTime()));
			CommandReturn commandReturn = itcommm.transPin(Util.HexToBin(factor), Util.HexToBin(String.format("06%sFFFFFFFF", data)));
			if ((commandReturn != null) && (commandReturn.transPin != null)) {
				mData = Util.BinToHex(commandReturn.transPin, 0, commandReturn.transPin.length);
			}
			return mData;
		} else if (ISwiperListener.MacDataIndex.equals(index)) {
			String macplain = null;
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			try {
				bos.write(String.valueOf(data.toCharArray()).getBytes());
				bos.write(0x80);
				while (bos.size() % 8 != 0) {
					bos.write(0x00);
				}
				bos.write(0x80);
				for (int i = 0; i < 7; i++) {
					bos.write(0x00);
				}
				byte[] macPlainBytes = bos.toByteArray();
				macplain = CommonUtils.bytesToHexString(macPlainBytes);
			} catch (IOException ioe) {
				HPLog.e(TAG, "", ioe);
				try {
					bos.close();
				} catch (IOException e) {
					HPLog.e(TAG, "", e);
				}
			}
			HPLog.e(TAG, "加密前Mac:" + macplain);
			//CommandReturn commandReturn = itcommm.Get_MAC(0, 1,Util.HexToBin(factor), Util.HexToBin(macplain));
			CommandReturn commandReturn = itcommm.calculateMac(1, 0, 1, null, Util.HexToBin(factor), Util.HexToBin(macplain));
			
			
			if ((commandReturn != null) && (commandReturn.Return_Result == 0x00)) {
				if (commandReturn.Return_PSAMMAC != null) {
					String mac = Util.BinToHex(commandReturn.Return_PSAMMAC, 0, commandReturn.Return_PSAMMAC.length);
					macStr = mac.substring(0, mac.length() - 8).toUpperCase();
				}
			}
			HPLog.e(TAG, "加密后Mac:" + macStr);
			return macStr;
		}
		return null;
	}


	
	
	// 格式化数据 type=0:关键数据 type=1 mac数据
	public String formatData(String data, int type) {
		int len;
		StringBuffer sb = new StringBuffer();
		if (mSwiperMode == SwiperMode.SUPER_TRANS) {
			HPLog.e(TAG, "super");
			sb.append(Convert.bytesToHexString(data.getBytes()));
		} else {
			HPLog.e(TAG, "normal");
			sb.append(Convert.bytesToHexString(CommonUtils.hexStringToBytes(data)));
		}

		if (type == 0) {
			len = sb.length();
			while ((len % 16) > 0) {
				sb.append("00");
				len = sb.length();
			}
		} else if (type == 1) { // mac
			sb.append("80");
			len = sb.length();
			while ((len % 16) > 0) {
				sb.append("00");
				len = sb.length();
			}
			sb.append("8000000000000000");
		}

		return sb.toString();
	}

	
	
	@Override
	public boolean isSwiperReady() {
		HPLog.i(TAG, ">>>>isSwiperReady<<<<" + isSwiperOk);
		return isSwiperOk;
	}

	@Override
	public SwiperModel getSwiperModel() {
		HPLog.i(TAG, ">>>>getSwiperModel<<<<");
		return SwiperModel.I21B_BLUETOOTH;
	}


	@Override
	public void onError(int arg0, String arg1) {
		HPLog.i(TAG, ">>>>onError<<<<int errorCode, String errorMsg =" + arg1);
		mData = null;
		mHTData.clear();
		mLock.unlock(AsynSwiperLock.IDLE);
	}


	@Override
	public void onICWaitingOper() {
		HPLog.i(TAG, ">>>>onICWaitingOper<<<<");
	}


	@Override
	public void onShowMessage(String arg0) {
		HPLog.i(TAG, ">>>>onShowMessage<<<<"+arg0);
	}


	@Override
	public void onTimeout() {
		HPLog.i(TAG, ">>>>onTimeout<<<<");
	}


	@Override
	public void onWaitingOper() {
		HPLog.i(TAG, ">>>>onWaitingOper<<<<");
	}


	@Override
	public void onWaitingPin() {
		HPLog.i(TAG, ">>>>onWaitingPin<<<<");
	}


	@Override
	public void onWaitingcard() {
		HPLog.i(TAG, ">>>>onWaitingcard<<<<");
	}

	
}
